package com.xthh._ble;


import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.os.Build;
import android.os.Handler;

import androidx.annotation.RequiresApi;

import com.xt.pro.BLEControlJni;
import com.xthh.XTCore;
import com.xthh._enum.HH_EnumErrorCode;
import com.xthh._function.HH_HexUtil;
import com.xthh._function.HH_Logging;
import com.xthh._function.HH_SystemUtil;
import com.xthh._struct.HH_T_SystemParams;
import com.xthh.fastble.BleManager;
import com.xthh.fastble.callback.BleNotifyCallback;
import com.xthh.fastble.callback.BleWriteCallback;
import com.xthh.fastble.data.BleDevice;
import com.xthh.fastble.exception.BleException;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class BLE {

    private static final String TAG = "XTHH_BLE";
    private List<BluetoothGattService> listBluetoothGattService;
    private BluetoothGattService currentBluetoothGattService;
    private BluetoothGattCharacteristic bluetoothGattCharacteristicNotify; // 通知特征
    private BluetoothGattCharacteristic bluetoothGattCharacteristicWrite;// 写特征

    private String xtUUID = "00002760-08c2-11e1-9073-0e8ac72e1001"; // 公司内部的UUID
    public int globa_n_WaitAnswerRunning = -1;
    private BleDevice bleDevice;
    private boolean bNotifySuccess = false;
    private boolean bGetCharacteristicResult = false;


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public BLE(HH_T_SystemParams tp, BleDevice bd) {
        bleDevice = bd;
        bGetCharacteristicResult = GetGattCharacteristic(tp);
    }

    public boolean IsGetCharacteristicResult(){
        return bGetCharacteristicResult;
    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public boolean Write(byte []data){
        if (data != null && data.length > 0)
            return Blewrite(bleDevice, currentBluetoothGattService, bluetoothGattCharacteristicWrite, data);
        return false;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private boolean GetGattCharacteristic(HH_T_SystemParams tp) {
        listBluetoothGattService = GattService(bleDevice);
        if (listBluetoothGattService != null && listBluetoothGattService.size() > 0) {
            for (int i = 0; i < listBluetoothGattService.size(); i++){
                bluetoothGattCharacteristicNotify = GattCharacteristicNotify(listBluetoothGattService.get(i));
                bluetoothGattCharacteristicWrite = GattCharacteristicWrite(listBluetoothGattService.get(i));
                if (bluetoothGattCharacteristicNotify != null && bluetoothGattCharacteristicWrite != null) {
                    currentBluetoothGattService = listBluetoothGattService.get(i);
                    // 开启接收数据（通知）
                    return Blenotify(tp, bleDevice, listBluetoothGattService.get(i), bluetoothGattCharacteristicNotify);
                }
            }
        } else {
            return false;
        }

        return true;
    }


    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private BluetoothGattCharacteristic GattCharacteristicNotify(BluetoothGattService gs) {

        for (BluetoothGattCharacteristic characteristic : gs.getCharacteristics()) {
            int charaProp = characteristic.getProperties();
            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                return characteristic;
            }
        }
        return null;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private BluetoothGattCharacteristic GattCharacteristicWrite(BluetoothGattService gs) {
        for (BluetoothGattCharacteristic characteristic : gs.getCharacteristics()) {
            int charaProp = characteristic.getProperties();
            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                return characteristic;
            } else if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
                return characteristic;
            }
        }
        return null;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private List<BluetoothGattService> GattService(BleDevice bd) {
        List<BluetoothGattService> list = new ArrayList<BluetoothGattService>();
        BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt(bd);
        if (gatt == null)
            return null;
        for (BluetoothGattService service : gatt.getServices()) {
            //Logging.i(TAG, "UUID:%s", service.getUuid());

            // 只保留我们自己需要刷图的UUID的服务
            String strUUID = service.getUuid().toString();
            if (strUUID.indexOf(xtUUID) != -1){
                //Logging.i(TAG, "UUID-已发现专用服务:%s", service.getUuid());
                list.add(service);
            }
        }

        return list;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private boolean Blenotify(HH_T_SystemParams tp, BleDevice bd, BluetoothGattService gs, BluetoothGattCharacteristic gc) {
        final boolean[] result = {false};
        final CountDownLatch latch = new CountDownLatch(1);

        BleManager.getInstance().notify(bd, gs.getUuid().toString(), gc.getUuid().toString(), new BleNotifyCallback() {
            @Override
            public void onNotifySuccess() {
                HH_Logging.i(TAG, tp, "onNotifySuccess");
                bNotifySuccess = true;
                result[0] = true;
                latch.countDown();
            }

            @Override
            public void onNotifyFailure(BleException exception) {
                HH_Logging.i(TAG, tp, "onNotifyFailure");
                result[0] = false;
                latch.countDown();
            }

            @Override
            public void onCharacteristicChanged(byte[] data) {
                HH_Logging.i(TAG, tp, "RECV1：onCharacteristicChanged:%s", HH_HexUtil.formatHexString(data, true));
                if (data != null && data.length > 0){
                    byte result[] = BLEControlJni.AnalysisResult2(data, data.length);

                    if (result != null){
                        if (result.length == 1){
                            if (result[0] == 1)
                                globa_n_WaitAnswerRunning = 0;
                            else
                                globa_n_WaitAnswerRunning = 2;
                        } else if (result.length > 1){
                            if (result[0] == 2){
                                HH_BT.globa_list_sub_page_date = new ArrayList<Integer>();
                                for (int i = 1; i < result.length; i++){
                                    HH_BT.globa_list_sub_page_date.add((int) result[i]);
                                }
                            } else if (result[0] == 3){
                                HH_Logging.i(TAG, tp, "RECV2：errorcode:%02X", result[1]);
                                if ((result[1] & 0xff) == 0xCD){
                                    globa_n_WaitAnswerRunning = 3;
                                    HH_SystemUtil.SendMessage(tp, XTCore.MSG_LOG, "", 0, HH_EnumErrorCode.BLE_IDENTITY_ENCRYPTION_FAIL.ordinal());
                                }
                            }
                        }
                    }
                }
            }
        });

        try {
            latch.await();
        } catch (InterruptedException e) {
        }

        return result[0];
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    private boolean Blewrite(BleDevice bd, BluetoothGattService gs, BluetoothGattCharacteristic gc, byte[] data) {
        final boolean[] result = {false};
        if (data == null && data.length <= 0){
            return result[0];
        }

        final CountDownLatch latch = new CountDownLatch(1);

        int nWaitCount = 0;
        while (!bNotifySuccess){
            HH_SystemUtil.Sleep(10);
            nWaitCount++;

            if (nWaitCount > 500 * 10){
                break;
            }
        }

        //HH_Logging.hex(TAG, data, "发送");
        BleManager.getInstance().write(bd, gs.getUuid().toString(), gc.getUuid().toString(), data, new BleWriteCallback() {
            @Override
            public void onWriteSuccess(int current, int total, byte[] justWrite) {
                result[0] = true;
                latch.countDown();
            }

            @Override
            public void onWriteFailure(BleException exception) {
                result[0] = false;
                latch.countDown();
            }
        });

        try {
            latch.await();
        } catch (InterruptedException e) {
        }

        return result[0];
    }
}
